/**
 * Copyright (c) 2018-2028, Chill Zhuang 庄骞 (smallchill@163.com).
 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.springblade.modules.huikecloud.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import io.swagger.annotations.Api;

import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.AllArgsConstructor;

import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;

import org.springblade.common.constant.CommonConstant;
import org.springblade.core.mp.support.Condition;
import org.springblade.core.mp.support.Query;
import org.springblade.core.secure.BladeUser;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.utils.Func;
import org.springblade.modules.huikecloud.entity.Host;
import org.springblade.modules.huikecloud.service.AsyncService;
import org.springblade.modules.huikecloud.service.IHostService;
import org.springblade.modules.huikecloud.utils.IPUtil;
import org.springblade.modules.system.entity.User;
import org.springblade.modules.system.service.IParamService;
import org.springblade.modules.system.service.IUserService;
import org.springframework.web.bind.annotation.*;
import com.baomidou.mybatisplus.core.metadata.IPage;
import org.springblade.modules.huikecloud.entity.Port;
import org.springblade.modules.huikecloud.vo.PortVO;
import org.springblade.modules.huikecloud.service.IPortService;
import org.springblade.core.boot.ctrl.BladeController;
import springfox.documentation.annotations.ApiIgnore;

import java.util.List;
import java.util.Map;

/**
 * 控制器
 *
 * @author Blade
 * @since 2021-07-08
 */
@RestController
@AllArgsConstructor
@RequestMapping("mapping/port")
@Api(value = "", tags = "接口")
public class PortController extends BladeController {

    private AsyncService asyncService;
    private IPortService portService;
    private IUserService userService;
    private IHostService hostService;

    /**
     * 详情
     */
    @GetMapping("/detail")
    @ApiOperationSupport(order = 1)
    @ApiOperation(value = "详情", notes = "传入port")
    public R<Port> detail(Port port) {
        Port detail = portService.getOne(Condition.getQueryWrapper(port));
        return R.data(detail);
    }

    /**
     * 分页
     */
    @GetMapping("/list")
    @ApiOperationSupport(order = 2)
    @ApiOperation(value = "分页", notes = "传入port")
    public R<IPage<Port>> list(@ApiIgnore @RequestParam Map<String, Object> port, Query query) {
//		IPage<Port> pages = portService.page(Condition.getPage(query), Condition.getQueryWrapper(port));
        QueryWrapper<Port> queryWrapper = Condition.getQueryWrapper((Map<String, Object>) port, Port.class);
        IPage<Port> pages = portService.page(Condition.getPage(query), queryWrapper);
        return R.data(pages);
    }

    /**
     * 自定义分页
     */
    @GetMapping("/page")
    @ApiOperationSupport(order = 3)
    @ApiOperation(value = "分页", notes = "传入port")
    public R<IPage<PortVO>> page(PortVO port, Query query) {
        IPage<PortVO> pages = portService.selectPortPage(Condition.getPage(query), port);
        return R.data(pages);
    }

    /**
     * 新增
     */
    @PostMapping("/save")
    @ApiOperationSupport(order = 4)
    @ApiOperation(value = "新增", notes = "传入port")
    public R save(@Valid @RequestBody Port port) {
        return R.status(portService.save(port));
    }

    /**
     * 修改
     */
    @PostMapping("/update")
    @ApiOperationSupport(order = 5)
    @ApiOperation(value = "修改", notes = "传入port")
    public R update(@Valid @RequestBody Port port) {
        return R.status(portService.updateById(port));
    }

    /**
     * 新增或修改
     */
    @PostMapping("/submit")
    @ApiOperationSupport(order = 6)
    @ApiOperation(value = "新增或修改", notes = "传入port")
    public R submit(@Valid @RequestBody Port port, BladeUser bladeUser) {
//       验证用户信息
        User user = userService.getById(bladeUser.getUserId());
        if (user == null) {
            return R.fail("非法操作，用户不存在！！！");
        } else if (StringUtils.checkValNull(user.getEmail())) {
            return R.fail("请在个人信息处完善邮箱后再操作");
        }
        port.setUserName(user.getRealName());
        port.setUserEmail(user.getEmail());

        long number = IPUtil.ipToLong(port.getIp());
        String mappingName = number + "-" + port.getPort() + "." + port.getMappingType() + ".huikecloud.net";
        port.setMappingName(mappingName);
        port.setStatus(0);


        QueryWrapper<Port> portQueryWrapper = new QueryWrapper<>();
//      如果已存在，删除原有映射
        portQueryWrapper.clear();
        List<Port> portList = portService.list(portQueryWrapper.lambda().eq(Port::getMappingName, mappingName));
        for (Port p : portList) {
            if ("administrator".equals(bladeUser.getRoleName()) || bladeUser.getUserId().equals(p.getCreateUser())) {
                portService.delMapping(p);
            } else {
                return R.fail("只允许删除/修改自己创建的映射");
            }
        }

        portQueryWrapper.clear();
        if ("web".equals(port.getMappingType())&&StringUtils.checkValNotNull(port.getMappingUrl())){
            portList = portService.list(portQueryWrapper.lambda().eq(Port::getMappingUrl, port.getMappingUrl()));
            for (Port p : portList) {
                if ("administrator".equals(bladeUser.getRoleName()) || bladeUser.getUserId().equals(p.getCreateUser())) {
                    portService.delMapping(p);
                } else {
                    return R.fail("映射路径已存在，请更换路径后重试");
                }
            }
        }else {
            port.setMappingUrl(mappingName);
        }

        Port byId =null;
        if (port.getId() != null) {
            byId= portService.getById(port.getId());
        }
        if (port.getId() != null && byId != null) {
            if ("administrator".equals(bladeUser.getRoleName()) || bladeUser.getUserId().equals(byId.getCreateUser())) {
                portService.delMapping(byId);
            } else {
                return R.success("只允许删除/修改自己创建的映射");
            }
        }

        R r = hostService.mapping(port, 1);
        if (HttpServletResponse.SC_BAD_REQUEST == r.getCode()){
            return r;
        }
        boolean submit = portService.submit(port);
        asyncService.sendAdminMail(mappingName, port.getIp()+":"+port.getPort()+ "\n"
                +"收到新的端口映射请求，请及时处理"+ "\n"
                +"http://"+CommonConstant.CLOUD_PROXY_IP+"/api/mapping/port/email_pass?id="+port.getId());
        return R.status(submit);

    }


    /**
     * 删除
     */
    @PostMapping("/remove")
    @ApiOperationSupport(order = 8)
    @ApiOperation(value = "删除", notes = "传入ids")
    public R remove(@ApiParam(value = "主键集合", required = true) @RequestParam String ids, BladeUser bladeUser) {
        List<Port> portList = portService.listByIds(Func.toLongList(ids));
        if (portList != null && portList.size() > 0) {
            for (Port s : portList) {
                if ("administrator".equals(bladeUser.getRoleName()) || bladeUser.getUserId().equals(s.getCreateUser())) {
                    portService.delMapping(s);
                } else {
                    return R.success("只允许删除自己创建的端口");
                }
            }
        }
        return R.success("删除成功");
    }

    /**
     * 通过
     */
    @PostMapping("/pass")
    @ApiOperationSupport(order = 6)
    @ApiOperation(value = "通过", notes = "传入id")
    public R pass(@ApiParam(value = "主键集合", required = true) @RequestParam String id) {
        Port port = portService.getById(id);
        if (port == null) {
            return R.fail("申请不存在");
        } else if (1 == port.getStatus()) {
            return R.fail("申请已通过，无需重复处理");
        }
        return R.status(portService.addMapping(port));
    }


    /**
     * 邮件链接通过申请
     */
    @GetMapping("/email_pass")
    @ApiOperationSupport(order = 9)
    @ApiOperation(value = "通过", notes = "传入id")
    public R email_pass(@ApiParam(value = "主键集合", required = true) @RequestParam String id) {
        Port port = portService.getById(id);
        if (port == null) {
            return R.fail("申请不存在");
        } else if (1 == port.getStatus()) {
            return R.fail("申请已通过，无需重复处理");
        }
        return R.status(portService.addMapping(port));
    }


}
